/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#ifndef BUILD_INDEX_SERVICE_JOB_H
#define BUILD_INDEX_SERVICE_JOB_H

#include "JobCommonInfo.h"
#include "JobMgr.h"
#include "BasicJob.h"
#include "define/Defines.h"
#include "nas_share/common/HetroCommonService.h"
#include "nas_share/common/HetroBaseStruct.h"
#include "define/Types.h"
#include "common/JsonHelper.h"
#include "DirCacheParser.h"
#include "ScanMgr.h"

enum class IndexType {
    HETRO_INDEX_FULL = 0,
    HETRO_INDEX_INC = 1,
    HOMO_INDEX_FULL = 2,
    HOMO_INDEX_INC = 3
};

enum class MetaFileVersion {
    METAFILEVERSION_1 = 0,
    METAFILEVERSION_2
};

class BuildIndexServiceJob : public HetroBaseStruct, public HetroCommonService {
public:
    BuildIndexServiceJob() {}
    ~BuildIndexServiceJob();
    int CheckBackupJobType();
    EXTER_ATTACK int PrerequisiteJob() override;
    EXTER_ATTACK int GenerateSubJob() override;
    EXTER_ATTACK int ExecuteSubJob() override;
    EXTER_ATTACK int PostJob() override;

    enum class SCANNER_TASK_STATUS {
        SCANNER_TASK_STATUS_INIT        = 0,
        SCANNER_TASK_STATUS_INPROGRESS  = 1,
        SCANNER_TASK_STATUS_SUCCESS     = 2,
        SCANNER_TASK_STATUS_ABORTED     = 3,
        SCANNER_TASK_STATUS_FAILED      = 4,
    };

private:
    // 索引任务StorageRepositoryExtendInfo结构体
    struct StorageRepositoryExtendInfo {
        bool isCurrentCopyRepo {};
        int timestamp {};
        std::string copyId;
        std::string productEsn;
        std::string fileSystemId;

        BEGIN_SERIAL_MEMEBER
        SERIAL_MEMBER_TO_SPECIFIED_NAME(isCurrentCopyRepo, isCurrentCopyRepo);
        SERIAL_MEMBER_TO_SPECIFIED_NAME(timestamp, timestamp);
        SERIAL_MEMBER_TO_SPECIFIED_NAME(copyId, copyId);
        SERIAL_MEMBER_TO_SPECIFIED_NAME(productEsn, productEsn);
        SERIAL_MEMBER_TO_SPECIFIED_NAME(fileSystemId, fileSystemId);
        END_SERIAL_MEMEBER
    };

    struct RfiGeneratationParam {
        std::string copyId;
        std::vector<std::string> rfiFiles;

        BEGIN_SERIAL_MEMEBER
        SERIAL_MEMBER_TO_SPECIFIED_NAME(copyId, copyId)
        SERIAL_MEMBER_TO_SPECIFIED_NAME(rfiFiles, rfiFiles)
        END_SERIAL_MEMEBER
    };

    int PrerequisiteJobInner() const;
    int GenerateSubJobInner();
    int ExecuteSubJobInner();
    int PostJobInner() const;

    bool StartScanner(ScanConfig& scanConfig);

    void ReportJob(AppProtect::SubJobStatus::type status);
    std::shared_ptr<AppProtect::BuildIndexJob> GetJobInfoBody();

    int IdentifyRepos();
    int IdentifyRepo(AppProtect::StorageRepository& repo);

    int ProcessHetroIndex();
    int ProcessHomoIndex();
    int ProcessHomoIncIndex();
    int ProcessHomoIncIndex2();
    int ProcessHomoScan(bool isCur);
    bool AddIpsRuleForSmb();
    bool DeleteIpsRuleForSmb();

    void PrepareForGenerateRfi(std::string preMetaFilePath, std::string curMetafilepath);
    void PrepareForHomoIncIndex(bool dcacheExist, bool isCur);

    void SetScanHashType(ScanConfig& scanConfig) const;
    std::shared_ptr<Module::DirCacheParser> CreateDcacheObj(const std::string& fname) const;

    void FillScanConfigForGenerateRfi(ScanConfig& scanConfig, bool isFull);
    void FillScanConfigForScan(ScanConfig& scanConfig, bool isCur);
    void FillScanConfigBaseOnProtocol(ScanConfig &scanConfig);
    void FillScanConfigBaseOnProtocolPrev(ScanConfig &scanConfig);

    bool CheckDcacheExist(std::string& metaFilePath, bool isCur);
    void MonitorScanner();
    
    static void GeneratedCopyCtrlFileCb(void *usrData, std::string ctrlFile);
    static void GeneratedHardLinkCtrlFileCb(void *usrData, std::string ctrlFile);
    static void GenerateRfiCtrlFileCb(void *usrData, RfiCbStruct cbParam);
    void PrintRepo(const AppProtect::StorageRepository& repo);
    void FillMonitorScannerVarDetails(SCANNER_TASK_STATUS& scanTaskStatus,
        AppProtect::SubJobStatus::type& jobStatus);

    static void ScannerCtrlFileCallBack(void *usrData, const std::string &ControlFilePath);
    static void ScannerHardLinkCallBack(void *usrData, const std::string &ControlFilePath);
    static void BackupDirMTimeCallBack(void *usrData, const std::string &ControlFilePath);
    static void BackupDelCtrlCallBack(void *usrData, const std::string &ControlFilePath);

    void CopyMetaFileToMetaRepo(bool isCur);
    void UnzipToWorkDir(bool isCur) const;

    bool UnzipCurMetafileToWorkDirV1(const std::string& metaFilePath);
    bool UnzipCurMetafileToWorkDirV2(const std::string& metaFilePath);
    bool UnzipPreMetafileToWorkDirV1(const std::string& metaFilePath);
    bool UnzipPreMetafileToWorkDirV2(const std::string& metaFilePath);
    bool CheckUnzipMetafileSucceed(const std::string& execCmd, const std::string& workDir);
    bool CheckMetafileExists(const std::string& workDir) const;

    bool CheckCifsConnectivity(const std::string& path);
    bool InitNasShareInfo();
    bool CheckSmbConnection(std::string serviceI, Module::SmbVersion version);
    bool GetValideServiceIP();

    std::string PrepareUnZipCommand(const std::string &workDir, const std::string &dcache,
        const std::string &fcache, const std::string &meta, const std::string &xmeta);

    std::shared_ptr<AppProtect::BuildIndexJob> m_indexPara = nullptr;
    std::shared_ptr<AppProtect::StorageRepository> m_cacheRepo = nullptr;
    std::shared_ptr<AppProtect::StorageRepository> m_preRepo = nullptr;
    std::shared_ptr<AppProtect::StorageRepository> m_curRepo = nullptr;
    std::shared_ptr<AppProtect::StorageRepository> m_metaRepo = nullptr;
    std::shared_ptr<AppProtect::StorageRepository> m_preMetaRepo = nullptr;
    std::shared_ptr<AppProtect::StorageRepository> m_indexRepo = nullptr;
    std::shared_ptr<StorageRepositoryExtendInfo> m_preRepoExtendInfo = nullptr;
    std::shared_ptr<StorageRepositoryExtendInfo> m_curRepoExtendInfo = nullptr;
    
    ScanConfig m_scanConfig {};
    IndexType m_indexType { IndexType::HETRO_INDEX_FULL };

    std::string m_workDir;
    MetaFileVersion m_preMetaFileVersion;
    MetaFileVersion m_curMetaFileVersion;
    std::atomic<bool> m_isPreparing {false};
    std::atomic<int> m_result {0};
    ProtectedNasShare m_nasShare;
    std::string m_serviceIP;
};

#endif